package net.fukure.android.pecabc.media;

import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;

import net.fukure.android.pecabc.listener.OnAudioListener;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;


public class AudioRecoder {

    private final static String LOG_TAG = "AndroidFFWMEMicRec";
    
    private int sampleAudioRateInHz = 22050;//44100
    private int audioChannel = 1;
    private AudioRecordRunnable audioRecordRunnable;
	private AudioRecord audioRecord;
    private List<OnAudioListener> listeners = new ArrayList<OnAudioListener>();

	public void start(){
        audioRecordRunnable = new AudioRecordRunnable();
        Thread audioThread = new Thread(audioRecordRunnable);
        audioThread.start();
    	Log.d(LOG_TAG,"start mic rec");
    }

    public void stop() {
    	audioRecordRunnable.runAudioThread = false;
        Log.i(LOG_TAG, "stop mic rec");
    }
    
	class AudioRecordRunnable implements Runnable {
	
	    volatile boolean runAudioThread = true;
	    
	    @Override
	    public void run() {
	        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
	
	        int bufferSize;
	        short[] audioData;
	        int bufferReadResult;
	        int audioChannel = AudioRecoder.this.audioChannel==2 ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;

	        bufferSize = AudioRecord.getMinBufferSize(
	        		sampleAudioRateInHz, 
	        		audioChannel,
	        		AudioFormat.ENCODING_PCM_16BIT);
	        audioRecord = new AudioRecord(
	        		MediaRecorder.AudioSource.MIC,
	        		sampleAudioRateInHz, 
	        		audioChannel,
	        		AudioFormat.ENCODING_PCM_16BIT,
	        		bufferSize);
	
	        Log.d(LOG_TAG, "bufferSize:"+bufferSize);
	        
	        audioData = new short[bufferSize];
	        
	        try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
	        
	        audioRecord.startRecording();

	        while (runAudioThread) {
	            bufferReadResult = audioRecord.read(audioData, 0, audioData.length);
	            if (bufferReadResult > 0) {
	                // Changes in this variable may not be picked up despite it being "volatile"
                	fireAudioBuffer(ShortBuffer.wrap(audioData, 0, bufferReadResult));
	            }
	        }
	        
	        release();
	        
	    }
	
	}
	
	public void release(){
		try{
	        if (audioRecord != null) {
	            audioRecord.stop();
	            audioRecord.release();
	            audioRecord = null;
	        }
		}catch(Exception e){
			
		}
	}

	public int getAudioChannel(){
        return audioChannel;
	}
	
	public int getSampleRate(){
		return sampleAudioRateInHz;
	}

	public void addAudioListener(OnAudioListener listener){
		listeners.remove(listener);
		listeners.add(listener);
	}

	public void removeAudioListener(OnAudioListener listener){
		listeners.remove(listener);
	}

	private void fireAudioBuffer(ShortBuffer buffer){
		for (int i = 0; i < listeners.size(); i++) {
			OnAudioListener listener = listeners.get(i);
			listener.onAudioBuffer(buffer);
		}
	}

}